package cn.edu.csmzxy.rk233x.auth_system.security.filter;

import cn.edu.csmzxy.rk233x.auth_system.security.UserDetailsServiceImpl;
import cn.edu.csmzxy.rk233x.auth_system.util.JwtUtil;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;

/**
 * @author wumxing
 * @date 2025/10/15 9:56
 * @description JWT认证过滤
 */

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private UserDetailsServiceImpl userDetailsService;
    // 从配置文件读取JWT请求头Key
    @Value("${jwt.header}")
    private String jwtHeader;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        try {
            // 1. 从请求头提取Token（格式：Authorization: Bearer <token>）
            String token = getTokenFromRequest(request);
            // 2. 验证Token有效性，且SecurityContext无认证信息
            if (token != null && jwtUtil.validateToken(token) && SecurityContextHolder.getContext().getAuthentication() == null) {
                // 3. 从Token解析用户名
                String username = jwtUtil.getUsernameFromToken(token);
                // 4. 查询用户详情（含权限）
                UserDetails userDetails = userDetailsService.loadUserByUsername(username);
                // 5. 构建Authentication对象并存入SecurityContext
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities()
                );
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        } catch (Exception e) {
            logger.error("JWT认证过滤器异常：{}", e);
        }
        // 6. 继续执行后续过滤器
        filterChain.doFilter(request, response);
    }
    // 提取Token的工具方法
    private String getTokenFromRequest(HttpServletRequest request) {
        String bearerToken = request.getHeader(jwtHeader);
        if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);  // 截取“Bearer ”后的Token字符串
        }
        return null;
    }
}